import axios from 'axios'
import L from 'lodash'
import {loginUserKey, submitToken, backendMenuId, urlPrefix} from '@/config/index.js'
import store from 'store'
import {alert, replaceNullDeep, dotData, copy} from './index'
import {getToken as authGetToken, loginOut as authLoginOut, getUserInfo} from '@/utils/auth'

export const getToken = authGetToken

const instance = axios.create({
  baseURL: urlPrefix + '/',
  headers: {
    'X-Custom-Header': 'Web',
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 建立拦截
instance.interceptors.request.use(config => {
  // 登陆token
  let headers = {}
  let token = getToken()
  if (token) {
    headers.token = token
  } else {
    // 如果config中有token（这里代表是临时token）
    headers.token = config.token
  }
  // 菜单编号
  const menuId = store.get(backendMenuId)
  if (menuId) {
    headers['menu-id'] = String(menuId)
  }
  // 删除一下空的params
  for (let k in config.params) {
    if (!config.params[k] && config.params[k] !== 0) {
      delete config.params[k]
    } else {
      config.params[k] = L.trim(config.params[k])
    }
  }
  return L.merge(config, {headers})
}, error => {
  return handleError(error)
})

let statusMap = new Map()

instance.interceptors.response.use(response => {
  // 过滤null
  const success = dotData(response, 'data.success')
  if (!success) {
    alert(dotData(response, 'data.error_message') || '系统报错')
  }
  return replaceNullDeep(response)
}, error => {
  return handleError(error)
})

// 基础方法
export const get = (url, params = {}, config = {}) => instance.get(url, L.merge(config, {params}))
export const post = (url, data = {}, params = {}, config = {}) => instance.post(url, data, L.merge(config, {params}))
export const request = (url, params = {}, config = {}) => instance.request(url, L.merge(config, {params}))
export const RequestDelete = (url, params = {}, config = {}) => instance.delete(url, L.merge(config, {params}))
export const head = (url, params = {}, config = {}) => instance.head(url, L.merge(config, {params}))
export const options = (url, params = {}, config = {}) => instance.options(url, L.merge(config, {params}))
export const put = (url, data = {}, params = {}, config = {}) => instance.put(url, data, L.merge(config, {params}))
export const patch = (url, data = {}, params = {}, config = {}) => instance.patch(url, data, L.merge(config, {params}))
export const handleError = (error) => {
  if (error.response) {
    // The request was made and the server responded with a status code
    // that falls out of the range of 2xx
    const status = L.get(error, 'response.status')
    if (status === 401) {
      authLoginOut(true)
    } else if (status === 402) {
      const headers = L.get(error, 'response.headers')
      const newToken = headers.get('resubmit-token')
      if (newToken) {
        store.set(submitToken, newToken)
      }
      alert('请勿重复提交')
    } else if (status === 503) {
      window.location.reload()
    } else if (status === 0) {
      if (window.navigator.onLine) {
        alert('网络连接异常')
      } else {
        alert('访问失败：请检查网络')
      }
    } else {
      // 此处处理一下 同一个状态码在4秒内只包一次错误
      if (!statusMap.has(status)) {
        alert('系统报错 status:' + status)
        statusMap.set(status, true)
        setTimeout(_ => {
          statusMap.delete(status)
        }, 4000)
      }
    }
  } else {
    // Something happened in setting up the request that triggered an Error
    console.error(error)
  }
  return Promise.reject(error)
}

/**
 * 是否登陆
 * @returns {boolean}
 */
export function isLogin() {
  return !!getToken()
}

/**
 * 登录
 */
export function login(data) {
  store.set(loginUserKey, data)
  window.location.href = '/'
}

/**
 * 登出
 */
export const logout = authLoginOut

/**
 * 获取用户信息
 */
export const getLoginUser = getUserInfo
/**
 * get 数据
 * @param url
 * @param params
 * @param config
 * @returns {json}
 */
export function httpGetResponse(url, params = {}, config = {}) {
  return get(url, params, config).then(response => {
    return response.data
  })
}

/**
 * post 数据
 * @param url string
 * @param data json
 * @param params json
 * @param config json
 * @returns {json}
 */
export function httpSuccessPost(url, data = {}, params = {}, config = {}) {
  return post(url, data, params, config).then(response => {
    return response.data
  })
}

/**
 * 表格数据
 * @param url
 * @param defaultParams
 * @param config
 * @returns {json}
 */
export function httpGetTable(url, defaultParams = {}, config = {}) {
  // 分页信息
  let params = copy(defaultParams, true)
  let pageSize = params.pageSize || 20
  let pageNum = params.pageNum || 1
  delete params.pageSize
  delete params.pageNum
  config.headers = L.merge(config.headers, {pageSize, pageNum})
  return get(url, params, config).then(response => {
    const success = dotData(response, 'data.success')
    let data = []
    let totalItem = 0
    let errorMessage = ''
    if (success) {
      data = dotData(response, 'data.data')
      totalItem = parseInt(response.headers['count'])
    }
    return {
      data,
      success,
      totalItem,
      error_message: errorMessage
    }
  })
}

// vue 安装
const install = (Vue, name = '$ajax') => {
  Object.defineProperty(Vue.prototype, name, {
    value: {
      get: httpGetResponse,
      post: httpSuccessPost,
      table: httpGetTable
    }
  })
}

export default {
  install,
  get,
  post,
  request,
  RequestDelete,
  head,
  options,
  put,
  patch
}
